window.onload = function () {
  function Mine(tr, td, mineNum, parent) {
    this.tr = tr; //生成多少行
    this.td = td; //生成多少列
    this.tds = new Array(this.td * this.tr); //用来存储生成的每一个td
    this.square = []; //用来存储生成的每一个格子的数据
    this.mineNumArr = []; //用来存储随机雷的值
    this.mineNum = mineNum; //有多少个雷
    this.parent = parent; //在哪个元素下生成
    this.flagArr = []; //用来存储标记为旗子的位置
  }
  Mine.prototype.createTable = function () {
    //去掉默认的contextmenu事件，否则会和右键事件同时出现。
    this.parent.oncontextmenu = function (e) {
      e.preventDefault();
    };
    this.parent.innerHTML = "";
    for (let i = 0; i < this.td; i++) {
      this.tds[i] = [];
      let trs = document.createElement("tr");
      for (let j = 0; j < this.tr; j++) {
        let tds = document.createElement("td");
        this.tds[i][j] = tds;
        let pos = [i, j];
        let that = this;
        tds.onmousedown = function (e) {
          that.play(e, this, pos);
        };
        trs.appendChild(tds);
      }
      this.parent.appendChild(trs);
    }
  };
  //获取随机的雷
  Mine.prototype.getMineNums = function () {
    let newArr = new Array(this.td * this.tr);
    let n = 0;
    for (let i = 0; i < this.tr; i++) {
      for (let j = 0; j < this.td; j++) {
        newArr.push(n++);
      }
    }
    //将newArr胡乱排序
    newArr.sort(() => {
      return 0.5 - Math.random();
    });
    //截取数组前面指定雷数为雷的位置
    this.mineNumArr = newArr.splice(0, this.mineNum);
  };
  // 根据随机的雷数，给square添加上数据信息
  Mine.prototype.addSquare = function () {
    let n = 0;
    for (let i = 0; i < this.tr; i++) {
      this.square[i] = [];
      for (let j = 0; j < this.td; j++) {
        if (this.mineNumArr.indexOf(n++) != -1) {
          this.square[i][j] = {
            type: "mine",
            x: i,
            y: j,
            check: false,
          };
        } else {
          this.square[i][j] = {
            type: "number",
            x: i,
            y: j,
            val: 0,
            check: false,
          };
        }
      }
    }
  };

  //   找某个方格周围的8个方格：
  // x-1,y-1    x,y-1  x+1,y-1
  // x-1,y      x,y    x+1,y
  // x-1,y+1    x-1,y+1 x+1,y+1
  Mine.prototype.getRound = function (x, y) {
    let result = [];
    for (var i = x - 1; i <= x + 1; i++) {
      for (var j = y - 1; j <= y + 1; j++) {
        if (
          i < 0 ||
          j < 0 ||
          j > this.td - 1 ||
          i > this.tr - 1 ||
          this.square[i][j].type == "mine" ||
          (i == x && j == y)
        ) {
          continue;
        } else {
          result.push([i, j]);
        }
      }
    }
    return result;
  };
  //雷四周的数字进行叠加
  Mine.prototype.addValue = function () {
    for (var i = 0; i < this.td; i++) {
      for (var j = 0; j < this.tr; j++) {
        if (this.square[i][j].type == "mine") {
          let result = this.getRound(i, j);
          if (result) {
            for (let k = 0; k < result.length; k++) {
              this.square[result[k][0]][result[k][1]].val++;
            }
          }
        }
      }
    }
    console.log(this.square);
  };
  //点击开始玩
  Mine.prototype.play = function (e, that, pos) {
    // debugger;
    if (e.button == 0 && that.className != "flag") {
      //左键点击事件
      //左键点击的是雷，游戏失败
      if (this.square[pos[0]][pos[1]].type == "mine") {
        that.className = "mine";
        //当前的雷改背景色为红色
        that.style.backgroundColor = "red";
        // 将所有的雷显示
        for (let i = 0; i < this.td; i++) {
          for (let j = 0; j < this.tr; j++) {
            if (this.square[i][j].type == "mine") {
              this.tds[i][j].className = "mine";
            }
          }
        }
        alert("游戏失败");
        //取消点击事件
        //所有的td都不可点击
        for (let i = 0; i < this.td; i++) {
          for (let j = 0; j < this.tr; j++) {
            this.tds[i][j].onmousedown = null;
          }
        }
      } else {
        if (this.square[pos[0]][pos[1]].val == 0) {
          that.className = classes[0];
          this.square[pos[0]][pos[1]].check = true;
          //0周围的数字都需要显示
          this.getZero(pos[0], pos[1]);
        } else {
          let val = this.square[pos[0]][pos[1]].val;
          that.innerText = val;
          that.className = classes[val];
          //解除td的点击事件
          that.onmousedown = null;
        }
      }
    } else if (e.button == 2) {
      if (that.className == "flag") {
        //如果是旗子，再次点击将取消这个旗子
        this.mineNum++;
        span.innerText = this.mineNum;
        that.className = "";
        let index;
        index = this.flagArr.some((item, i) => {
          if (item[0] == pos[0] && item[1] == pos[1]) {
            index = i;
            return true;
          }
        });
        this.flagArr.splice(index, 1);
      } else {
        //右键点击事件
        this.mineNum--;
        span.innerText = this.mineNum;
        that.className = "flag";
        //将坐标存起来
        this.flagArr.push([pos[0], pos[1]]);
        //当所有的旗子都标记完之后判断，只要有一个是雷，就游戏失败
        if (this.mineNum == 0) {
          let flag = false;
          for (let i = 0; i < this.flagArr.length; i++) {
            if (
              this.square[this.flagArr[i][0]][this.flagArr[i][1]].type != "mine"
            ) {
              flag = true;
              // 将所有的雷显示
              for (let i = 0; i < this.td; i++) {
                for (let j = 0; j < this.tr; j++) {
                  if (this.square[i][j].type == "mine") {
                    this.tds[i][j].className = "mine";
                  }
                }
              }
            }
          }
          if (flag) {
            //所有的td都不可点击
            for (let i = 0; i < this.td; i++) {
              for (let j = 0; j < this.tr; j++) {
                this.tds[i][j].onmousedown = null;
              }
            }
            alert("游戏失败！");
          } else {
            alert("恭喜！游戏通过");
          }
        }
      }
    }
  };
  //当点击0的时候
  Mine.prototype.getZero = function (x, y) {
    let resArr = this.getRound(x, y);
    for (let i = 0; i < resArr.length; i++) {
      let resVal = this.square[resArr[i][0]][resArr[i][1]].val;
      let check = this.square[resArr[i][0]][resArr[i][1]].check;
      //解除td的点击事件
      this.tds[resArr[i][0]][resArr[i][1]].onmousedown = null;
      if (resVal == 0 && !check) {
        this.square[resArr[i][0]][resArr[i][1]].check = true;
        this.tds[resArr[i][0]][resArr[i][1]].className = classes[0];
        this.getZero(resArr[i][0], resArr[i][1]);
      } else if (resVal != 0) {
        this.tds[resArr[i][0]][resArr[i][1]].innerText = resVal;
        this.tds[resArr[i][0]][resArr[i][1]].className = classes[resVal];
        //解除td的点击事件
        this.tds[resArr[i][0]][resArr[i][1]].onmousedown = null;
      }
    }
  };
  //初始化方法
  Mine.prototype.init = function () {
    span.innerText = this.mineNum;
    this.getMineNums();
    this.addSquare();
    this.addValue();
    this.createTable();
  };
  //生成实例
  let parent = document.getElementsByTagName("table")[0];
  let span = document.getElementsByTagName("span")[0];
  //根据不同级别按钮生成不同的mine实例
  let btns = document.getElementsByTagName("button");
  let restartBtn = document.getElementById("restart");
  let mine;
  //所有单元格对应值对应的类：例如，格子的值为0，则类名为zero
  let classes = [
    "zero",
    "one",
    "two",
    "three",
    "four",
    "five",
    "six",
    "seven",
    "eight",
  ];
  let numArr = [
    [9, 9, 10],
    [16, 16, 40],
    [28, 28, 99],
  ];
  let active = 0;
  for (let i = 0; i < btns.length - 1; i++) {
    btns[i].onclick = function () {
      btns[active].className = "";
      this.className = "active";
      active = i;
      mine = new Mine(numArr[i][0], numArr[i][1], numArr[i][2], parent);
      mine.init();
    };
  }
  btns[0].onclick();
  //重新开始按钮
  restartBtn.onclick = function () {
    mine = new Mine(
      numArr[active][0],
      numArr[active][1],
      numArr[active][2],
      parent
    );
    mine.init();
  };
};
